with v8.Class_Template, v8.Class_Arguments;
with v8.Class_Value, v8.Class_String;
limited with v8.Class_Function, v8.Class_Object, v8.Class_Object_Template, v8.Class_Signature;
package v8.Class_Function_Template is

   type Function_Template (<>) is new v8.Class_Template.Template with private;
   type Pointer is access all Function_Template;
   --  A FunctionTemplate is used to create functions at runtime.
   --  There can only be one function created from a FunctionTemplate in a context.
   --  The lifetime of the created function is equal to the lifetime of the context.
   --  So in case the embedder needs to create temporary functions that can be collected using Scripts is preferred.
   --  A FunctionTemplate can have properties, these properties are added to the function object when it is created.
   --  A FunctionTemplate has a corresponding instance template which is used to create object instances when the function is used as a constructor.
   --  Properties added to the instance template are added to each object instance.
   --  A FunctionTemplate can have a prototype template. The prototype template is used to create the prototype object of the function.


   type Function_Template_Array is array (Positive range <>) of Pointer;

   function Create
     (callback  : v8.Class_Arguments.Invocation_Callback;
      data      : v8.Class_Value.Pointer := null;
      signature : access v8.Class_Signature.Signature := null
     ) return Pointer;

   function Get_Function
     (this : in out Function_Template
     ) return v8.Class_Function.Pointer;
   -- Returns the unique function instance in the current execution context
   --  -- return Local<Function>

   procedure Set_Call_Handler
     (this     : in out Function_Template;
      callback : v8.Class_Arguments.Invocation_Callback;
      data     : v8.Class_Value.Pointer := null);
   -- Set the call - handler callback for a FunctionTemplate.  This
   -- callback is called whenever the function created from this
   -- FunctionTemplate is called.

   function Instance_Template
     (this : in out Function_Template
     ) return v8.Class_Object_Template.Pointer;
   -- ../include/v8.h:2200

   procedure Inherit (this : in out Function_Template; parent : Pointer);
   -- Causes the function template to inherit from a parent function template

   function Prototype_Template
     (this : access Function_Template
     ) return v8.Class_Object_Template.Pointer;
   -- A PrototypeTemplate is the template used to create the prototype object
   -- of the function created by this template.

   procedure Set_Class_Name
     (this : in out Function_Template;
      name : v8.Class_String.Pointer);
   -- Set the class name of the FunctionTemplate.  This is used for
   -- printing objects created with the function created from the
   -- FunctionTemplate as its constructor.

   procedure Set_Hidden_Prototype
     (this  : in out Function_Template;
      value : bool);
   -- Determines whether the __proto__ accessor ignores instances of
   -- the function template.  If instances of the function template are
   -- ignored, __proto__ skips all instances and instead returns the
   -- next object in the prototype chain.
   -- Call with a value of true to make the __proto__ accessor ignore
   -- instances of the function template.  Call with a value of false
   -- to make the __proto__ accessor not ignore instances of the
   -- function template.  By default, instances of a function template
   -- are not ignored.

   procedure Read_Only_Prototype (this : in out Function_Template);
   --  Sets the ReadOnly flag in the attributes of the 'prototype' property
   --  of functions created from this FunctionTemplate to true.

   function Has_Instance
     (this   : access Function_Template;
      object : v8.Class_Object.Pointer
     ) return Bool;
   -- Returns true if the given object is an instance of this function template.


   --  The following example shows how to use a FunctionTemplate:
   --
   --      v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
   --      t->Set("func_property", v8::Number::New(1));
   --
   --      v8::Local<v8::Template> proto_t = t->PrototypeTemplate();
   --      proto_t->Set("proto_method", v8::FunctionTemplate::New(InvokeCallback));
   --      proto_t->Set("proto_const", v8::Number::New(2));
   --
   --      v8::Local<v8::ObjectTemplate> instance_t = t->InstanceTemplate();
   --      instance_t->SetAccessor("instance_accessor", InstanceAccessorCallback);
   --      instance_t->SetNamedPropertyHandler(PropertyHandlerCallback, ...);
   --      instance_t->Set("instance_property", Number::New(3));
   --
   --      v8::Local<v8::Function> function = t->GetFunction();
   --      v8::Local<v8::Object> instance = function->NewInstance();
   --
   --  Let's use "function" as the JS variable name of the function object and "instance" for the instance object created above.
   --  The function and the instance will have the following properties :
   --
   --     func_property in function == true;
   --     function.func_property == 1;
   --
   --     function.prototype.proto_method() invokes 'InvokeCallback'
   --     function.prototype.proto_const == 2;
   --
   --     instance instanceof function == true;
   --     instance.instance_accessor calls 'InstanceAccessorCallback'
   --     instance.instance_property == 3;
   --
   --  A FunctionTemplate can inherit from another one by calling the FunctionTemplate::Inherit method.
   --  The following graph illustrates the semantics of inheritance :
   --
   --     FunctionTemplate Parent  -> Parent() . prototype -> { }
   --       ^                                                  ^
   --       | Inherit(Parent)                                  | .__proto__
   --       |                                                  |
   --     FunctionTemplate Child   -> Child()  . prototype -> { }
   --
   --  A FunctionTemplate 'Child' inherits from 'Parent',
   --  the prototype object of the Child () function has __proto__ pointing to the Parent () function's prototype object.
   --  An instance of the Child function has all properties on Parent's instance templates.
   --
   --  Let Parent be the FunctionTemplate initialized in the previous section and create a Child FunctionTemplate by:
   --
   --     Local<FunctionTemplate> parent = t;
   --     Local<FunctionTemplate> child = FunctionTemplate::New();
   --     child->Inherit(parent);
   --
   --     Local<Function> child_function = child->GetFunction();
   --     Local<Object> child_instance = child_function->NewInstance();
   --
   --  The Child function and Child instance will have the following properties:
   --
   --     child_func.prototype.__proto__ == function.prototype;
   --     child_instance.instance_accessor calls 'InstanceAccessorCallback'
   --     child_instance.instance_property == 3;

private
   type Function_Template is new v8.Class_Template.Template with null record;

   pragma Import (CPP, Create, "_ZN2v816FunctionTemplate3NewEPFNS_6HandleINS_5ValueEEERKNS_9ArgumentsEES3_NS1_INS_9SignatureEEE");
   pragma Import (CPP, Get_Function, "_ZN2v816FunctionTemplate11GetFunctionEv");
   pragma Import (CPP, Set_Call_Handler, "_ZN2v816FunctionTemplate14SetCallHandlerEPFNS_6HandleINS_5ValueEEERKNS_9ArgumentsEES3_");
   pragma Import (CPP, Instance_Template, "_ZN2v816FunctionTemplate16InstanceTemplateEv");
   pragma Import (CPP, Inherit, "_ZN2v816FunctionTemplate7InheritENS_6HandleIS0_EE");
   pragma Import (CPP, Prototype_Template, "_ZN2v816FunctionTemplate17PrototypeTemplateEv");
   pragma Import (CPP, Set_Class_Name, "_ZN2v816FunctionTemplate12SetClassNameENS_6HandleINS_6StringEEE");
   pragma Import (CPP, Set_Hidden_Prototype, "_ZN2v816FunctionTemplate18SetHiddenPrototypeEb");
   pragma Import (CPP, Read_Only_Prototype, "_ZN2v816FunctionTemplate17ReadOnlyPrototypeEv");
   pragma Import (CPP, Has_Instance, "_ZN2v816FunctionTemplate11HasInstanceENS_6HandleINS_5ValueEEE");

end v8.Class_Function_Template;
